#include"../../include/server.h"

using namespace std;


TCP_Server::TCP_Server(){
    SqlInit();
}
TCP_Server::~TCP_Server(){
}


void TCP_Server::SqlInit(){
    SqlQuery Q;
    if(!Q.open(Fooddb)){
	cout<<"open database fail"<<endl;
    }else{
	if(!Q.exec(SqlInitHome)){
	    cout<<"table home init fail "<<endl;
	}
	if(!Q.exec(SqlinitMenu)){
	    cout<<"table menu init fail "<<endl;
	}
	if(!Q.exec(SqlinitOrder)){
	    cout<<"table desk init fail "<<endl;
	}
	Q.close();
   }
}



bool SendMessage(SubPthreadInfo *s,ContentList *pSend){
    
    //--------调试中打印发送的内容--------------
    /*

    ContentList *pshow=pSend;
    while(pshow){
	cout<<pshow->FoodNum<<"|"<<pshow->FoodSum<<endl;
	pshow=pshow->next;
    }
    */
    //----------------------
    
    ContentList *p=pSend;
    s->Msg.ContentSum=0;
    char buf[1024]={0};
    char buf1[MaxPackSize-HeaderSize]={0};
    Content tmp={0,0,0};
    while(p!=NULL){
	ushort pos=s->Msg.ContentSum*ContentSize;
	++s->Msg.ContentSum;
	tmp.FoodNum=p->FoodNum;
	tmp.FoodSum=p->FoodSum;
	strcpy(tmp.Remark,p->Remark);
	memcpy(&buf1[pos],&tmp,ContentSize);
	p=p->next;
	if((s->Msg.ContentSum>=MaxContentSum)&&(p!=NULL)){
	    s->Msg.PackIsEnd =NoEnd;
	    memcpy(buf,&s->Msg,HeaderSize);
	    memcpy(&buf[HeaderSize],buf1,MaxPackSize-HeaderSize);
	    write(*s->accpet_fd,buf,1024);
	    s->Msg.ContentSum=0;
	    memset(buf1,0,MaxPackSize-HeaderSize);
	}
    }
    s->Msg.PackIsEnd =IsEnd;
    memcpy(buf,&s->Msg,HeaderSize);
    memcpy(&buf[HeaderSize],buf1,MaxPackSize-HeaderSize);
    int ret=write(*s->accpet_fd,buf,1024);
    if(ret<=0){
	perror("write");
	return false;
    }

    //--------调试中打印发送的内容--------------
    /*
    cout<<"send s->Msg.client="<<s->Msg.client<<endl;
    cout<<"send s->Msg.PackIsEnd="<<s->Msg.PackIsEnd<<endl;
    cout<<"send s->Msg.ConnetType="<<s->Msg.ConnetType<<endl;
    cout<<"send s->Msg.TableNum="<<s->Msg.TableNum<<endl;
    cout<<"send s->Msg.ContentSum="<<s->Msg.ContentSum<<endl;
    write(0,"send buf=",9);
    write(0,buf,1024);
    */
    //----------
    return true;

}

bool InsertSqlite(string SSql){
    SqlQuery Q;
    if(!Q.open(Fooddb)){
	cout<<"open database fail"<<endl;
	return false;
    }
    if(!Q.exec(SSql)){
	cout<<"exec table fail"<<endl;
	return false;
    }
    return true;
}
ContentList* SelectSqlite(string SSql){
    SqlQuery Q;
    if(!Q.open(Fooddb)){
	cout<<"open database fail"<<endl;
    }
    return Q.Query(SSql).GetResult();
}


void* DeelThread(void* data){
    cout<<"New pthread!"<<endl;
    SubPthreadInfo *s=(SubPthreadInfo*)data;
    ContentList *p = new ContentList;
    p->next=NULL;
    ContentList *p1 =p;
    ContentList *p2=NULL;
    ushort i=0;
    //--------调试中打印发送的内容--------------
    /*
    cout<<"receive s->Msg.client="<<s->Msg.client<<endl;
    cout<<"receive s->Msg.PackIsEnd="<<s->Msg.PackIsEnd<<endl;
    cout<<"receive s->Msg.ConnetType="<<s->Msg.ConnetType<<endl;
    cout<<"receive s->Msg.TableNum="<<s->Msg.TableNum<<endl;
    cout<<"receive s->Msg.ContentSum="<<s->Msg.ContentSum<<endl;
    */
    //-------------------
    while(s->Msg.ContentSum--){
	ContentList *tmp= new ContentList;
	memcpy(&tmp->FoodNum,&s->Content[0+i],SizeofTypeInContent);
	memcpy(&tmp->FoodSum,&s->Content[0+SizeofTypeInContent+i],SizeofTypeInContent);
	memcpy(tmp->Remark,&s->Content[0+SizeofTypeInContent+SizeofTypeInContent+i],RemarkSize);
	i=i+SizeofTypeInContent+SizeofTypeInContent+RemarkSize;
	tmp->next=NULL;
	p1->next=tmp;
	tmp->pre=p1;
	p1=p1->next;
    }
    p=p->next;
    if(s->Msg.ConnetType==ConnetChangeTable){
	string SSql="update home set status=5 where id=";
	SSql+=itoa(s->Msg.TableNum);
	InsertSqlite(SSql);	
	cout<<"change table"<<endl;
	SSql="select id,name from home where status=0";
	p2=SelectSqlite(SSql);
    }else if(s->Msg.ConnetType==ConnetGetTable){
	string SSql="select id,name from home where status=0";
	p2=SelectSqlite(SSql);
    }else if(s->Msg.ConnetType==ConnetGetChangeTable){
	string SSql="select id,name from home where status=5";
	p2=SelectSqlite(SSql);
    }else if(s->Msg.ConnetType==ConnetGetUsedTable){
	string SSql="select id,name,status from home where status=1 or status=2 or status=4";
	p2=SelectSqlite(SSql);
    }else if(s->Msg.ConnetType==ConnetGetFood){
	string SSql="select id,name,price from menu where status>0";
	p2=SelectSqlite(SSql);
    }else if(s->Msg.ConnetType==ConnetDeelChangeTable){
	string SSql="update home set status=0 where id=";
	SSql+=itoa(s->Msg.TableNum);
	cout<<SSql<<endl;
	InsertSqlite(SSql);	
    }else if(s->Msg.ConnetType==ConnetOrderTable){
	string SSql="update home set status=1 where id=";
	SSql+=itoa(s->Msg.TableNum);
	SSql+=" and status=0";
	InsertSqlite(SSql);	
    }else if(s->Msg.ConnetType==ConnetOrderFood){
	while(p){
	    string SSql="insert into desk values(";
	    SSql+=itoa(p->FoodNum);
	    SSql+=",\"";
	    SSql+=p->Remark;
	    SSql+="\",";
	    SSql+=itoa(p->FoodSum);
	    SSql+=",";
	    SSql+=itoa(s->Msg.TableNum);
	    SSql+=",1)";
	    InsertSqlite(SSql);
	    p=p->next;
	}
    }else if(s->Msg.ConnetType==ConnetAddFood){
	while(p){
	    //string SSql="update desk set sum=sum+";
	    string SSql="update desk set sum=";
	    SSql+=itoa(p->FoodSum);
	    SSql+=" where id=";
	    SSql+=itoa(p->FoodNum);
	    SSql+=" and ";
	    SSql+="status=1";
	    SSql+=" and tablenum=";
	    SSql+=itoa(s->Msg.TableNum);
	    InsertSqlite(SSql);
	    p=p->next;
	}
    }else if(s->Msg.ConnetType==ConnetAddNewFood){
	while(p){

	    string SSql="insert into desk values(";
	    SSql+=itoa(p->FoodNum);
	    SSql+=",\"";
	    SSql+=p->Remark;
	    SSql+="\",";
	    SSql+=itoa(p->FoodSum);
	    SSql+=",";
	    SSql+=itoa(s->Msg.TableNum);
	    SSql+=",1)";
	    cout<<"add food ="<<SSql<<endl;
	    InsertSqlite(SSql);
	    p=p->next;
	}
	 
    
    }else if(s->Msg.ConnetType==ConnetGetOrderFood){
	string SSql;
	SSql="select id,name,sum from desk where tablenum=";
	SSql+=itoa(s->Msg.TableNum);
	p2=SelectSqlite(SSql);

    }else if(s->Msg.ConnetType==ConnetDeleteFood){
	string SSql;
	while(p){
	    SSql="update desk set sum=sum-";
	    SSql+=itoa(p->FoodSum);
	    SSql+=" where id=";
	    SSql+=itoa(p->FoodNum);
	    SSql+=" and ";
	    SSql+="status=1";
	    SSql+=" and tablenum=";
	    SSql+=itoa(s->Msg.TableNum);
	    InsertSqlite(SSql);
	    p=p->next;
	}
	SSql="delete from desk where tablenum=";
	SSql+=itoa(s->Msg.TableNum);
	SSql+=" and sum<=0";
	InsertSqlite(SSql);

    
    }else if(s->Msg.ConnetType==ConnetCallWaiter){
	string SSql;
	if(s->Msg.client==OrderClient){
	SSql="update home set status=2 where id=";
	SSql+=itoa(s->Msg.TableNum);
	}else if(s->Msg.client==ReceptionClient){
	SSql="update home set status=1 where id=";
	SSql+=itoa(s->Msg.TableNum);
	
	}
	InsertSqlite(SSql);

    }else if(s->Msg.ConnetType==ConnetAccount){
	string SSql;
	if(s->Msg.client==OrderClient){
	SSql="update home set status=3 where id=";
	SSql+=itoa(s->Msg.TableNum);
	}else if(s->Msg.client==ReceptionClient){
	SSql="update home set status=0 where id=";
	SSql+=itoa(s->Msg.TableNum);
	}
	InsertSqlite(SSql);
 
    
    }else if(s->Msg.ConnetType==ConnetAllTable){
	string SSql="select id,name,status from home";
	p2=SelectSqlite(SSql);
   
    }else if(s->Msg.ConnetType==ConnetGetCallWaiter){
	string SSql="select id,name from home where status=2";
	p2=SelectSqlite(SSql);

    }else if(s->Msg.ConnetType==ConnetGetAccount){
	string SSql="select id,name from home where status=3";
	p2=SelectSqlite(SSql);
    }else if(s->Msg.ConnetType==ConnetGetDownFood){
	string SSql="select id,name,price from menu where status=0";
	p2=SelectSqlite(SSql);
    
    }else if(s->Msg.ConnetType==ConnetOkFood){
	string SSql;
	if(s->Msg.client==CookClient){
	    SSql="update home set status=4 where id=";
	    SSql+=itoa(s->Msg.TableNum);
	    InsertSqlite(SSql);
	}else if(s->Msg.client==ReceptionClient){
	    SSql="select id, name from home where status=4";
	    p2=SelectSqlite(SSql);
	}
	
    }else if(s->Msg.ConnetType==ConnetFinishFood){
	string SSql="update home set status=1 where id=";
	SSql+=itoa(s->Msg.TableNum);
	InsertSqlite(SSql);
    }else if(s->Msg.ConnetType==ConnetNewFood){
	while(p){
	    string SSql="insert into menu values((select max(id) from menu)+1,\"";
	    SSql+=p->Remark;
	    SSql+="\",";
	    SSql+=itoa(p->FoodSum);
	    SSql+=",1)";
	    InsertSqlite(SSql);
	    p=p->next;
	}
    }else if(s->Msg.ConnetType==ConnetUpOldFood){
	while(p){
	    string SSql="update menu set status=1 where id=";
	    SSql+=itoa(p->FoodNum);
	    cout<<"SSql="<<SSql<<endl;
	    InsertSqlite(SSql);
	    p=p->next;
	}

    }else if(s->Msg.ConnetType==ConnetOldFood){
	while(p){
	    string SSql="update menu set status=0 where name=\"";
	    SSql+=p->Remark;
	    SSql+="\"";
	    InsertSqlite(SSql);
	    p=p->next;
	}
    }
    SendMessage(s,p2);
    delete p;
    delete p2;
    
    return NULL;

}

void TCP_Server::ServerEpoll(){
    int EpollInstance;
    int EpollStatus;
    int ReturnValue;
    int PthreadNum =0;
    unsigned int Len;
    epoll_event Event,EventSum[20];
    
    socket_fd = socket(AF_INET,SOCK_STREAM,0);
    if(socket_fd==-1){
	perror("socket");
	return ;
    }
    
    ServerIP.sin_family = AF_INET;
    ServerIP.sin_port =htons(ServerPort);
    if(inet_pton(AF_INET,ServerLocalHost,&ServerIP.sin_addr.s_addr)<=0){
	perror("inet_pton");
	return ;
    }
    ReturnValue = bind(socket_fd,(struct sockaddr*)&ServerIP,sizeof(ServerIP));
    if(ReturnValue==-1){
	perror("bind");
	return ;
    }
    ReturnValue = listen(socket_fd,30);
    if(ReturnValue==-1){
	perror("listen");
	return ;
    }
    

    EpollInstance = epoll_create(256);

    if(EpollInstance==-1){
	perror("epoll_create");
	return ;
    }
    Event.data.fd = socket_fd;
    Event.events = EPOLLIN|EPOLLET;

    ReturnValue = epoll_ctl(EpollInstance,EPOLL_CTL_ADD,socket_fd,&Event);

    while(1){
	EpollStatus = epoll_wait(EpollInstance,EventSum,20,-1);
	if(EpollStatus < 0){
	    perror("epoll_wait");
	    continue;
	}else if(EpollStatus == 0){
	   cout<<"time out"<<endl;
	   continue;
	}else{
	    for(int i=0;i<EpollStatus;++i){
		if(EventSum[i].events == EPOLLIN|EPOLLET && EventSum[i].data.fd == socket_fd){
		   ++PthreadNum;
		   if(PthreadNum==MaxConnet){
			PthreadNum=0; 
		   }
		   Len = sizeof(ClientIP[PthreadNum]);

		   accpet_fd[PthreadNum]=accept(socket_fd,(struct sockaddr*)&ClientIP[PthreadNum],&Len);
		   cout<<"新客户端连接，IP地址："<<inet_ntoa(ClientIP[PthreadNum].sin_addr)<<"，端口号："<<ntohs(ClientIP[PthreadNum].sin_port)<<endl;
    
		   if(accpet_fd[PthreadNum]<0){
			perror("accept");
			PthreadNum--;
			continue;
		   }else if(accpet_fd[PthreadNum]>0){
		       Event.data.fd = accpet_fd[PthreadNum];
		       Event.events = EPOLLIN|EPOLLET;
		       epoll_ctl(EpollInstance,EPOLL_CTL_ADD,accpet_fd[PthreadNum],&Event);
		       continue;
		   }

		}else if(EventSum[i].events == EPOLLIN|EPOLLET){
		
		    for(int j=0;j<=PthreadNum;j++){
			if(EventSum[i].data.fd==accpet_fd[j]){
			    ReturnValue=read(accpet_fd[j],&PInfo[j].Msg,HeaderSize);
			    if(ReturnValue<=0){
				epoll_ctl(EpollInstance,EPOLL_CTL_DEL,accpet_fd[j],EventSum);
				cout<<"一个客户端断开"<<endl;

			    }else{
				ReturnValue=read(accpet_fd[j],PInfo[j].Content,RWMaxSize-HeaderSize);

				cout<<"客户端发来请求，IP地址："<<inet_ntoa(ClientIP[j].sin_addr)<<"，端口号："<<ntohs(ClientIP[j].sin_port)<<endl;
    
				PInfo[j].accpet_fd=&accpet_fd[j];
				PInfo[j].EpollInstance=&EpollInstance;
				PInfo[j].EventSum=&EventSum[j];
				PInfo[j].ClientIP=&ClientIP[j];
		
				pthread_create(&PID[j],NULL,DeelThread,(void*)&PInfo[j]);
			    }
			}
		    }
		}
	    }
	}
    }

    close(socket_fd);
}



int main()
{
    TCP_Server server;
    server.ServerEpoll();
    return 0;
}
